import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'dva';
import { Icon } from 'react-fa';
import { Form, AutoComplete, Input, Button, Transfer, Tree } from 'antd';
import Layout from '@/components/Layout';
import TabManager, { Tabs } from '@/components/Tabs';
import Dialog from '@/components/Dialog';
import { getQueryKeywords, createAction } from '@/utils';
import { getNodes, search, check } from '@/services/group';
import settings from '@/settings';
import GroupContext from './groupContext';
import api from '@/api'

const { TreeNode } = Tree;

const ModelForm = Form.create()(props => {
  const dispatch = useDispatch()

  const [activeKey, setActiveKey] = useState("1")
  const [expandedKeys, setExpandedKeys] = useState([])

  const {
    roleIds,
    data = {},
    roles = [],
    groups = [],
    groupIds = [],
    groupPaths = []
  } = useSelector(_ => _.group)

  if (groupPaths.length) {
    const paths = groupPaths.flatMap(_ => _.split('/'))
    setExpandedKeys(paths)
    dispatch(createAction('user/updateState')({
      groupIds: groupPaths.map(_ => _.split('/')[_.split('/').length - 1]),
    }));
  }

  const {
    id,
    form: { validateFields, getFieldDecorator }
  } = props

  useEffect(() => {
    if (id) {
      dispatch(createAction('group/fetchOne')({
        id
      }));
    }
  }, [dispatch, id]);

  useEffect(() => {
    dispatch(createAction('group/fetchGroups')());
    dispatch(createAction('group/fetchRoles')());
  }, [dispatch]);

  const handleSubmit = (_, callback) => {
    validateFields((err, values) => {
      if (err) {
        setActiveKey("1")
      } else {
        callback({
          ...values,
          roleIds,
        });
      }
    });
  };
  props.register(handleSubmit)

  const handleChange = targetKeys => {
    dispatch(createAction('group/updateState')({
      roleIds: targetKeys,
    }));
  };
  const renderTreeNodes = (data = []) =>
    data.map(item => {
      if (item.children) {
        return (
          <TreeNode title={item.name} selectable={false} key={item.id} dataRef={item} icon={<Icon name="folder-open" />}>
            {renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return (
        <TreeNode {...item} title={item.name} selectable={false} key={item.id} dataRef={item} icon={<Icon name="folder-open" />} />
      );
    });
  const onCheck = (checkedKeys, { checked, node }) => {
    let _checkedKeys = []
    if (checked) {
      _checkedKeys = [node.props.dataRef.id]
    }
    dispatch(createAction('group/updateState')({
      groupIds: _checkedKeys
    }));
  };
  // const onSelect = (selectedKeys, { selected, node }) => {
  //   let _checkedKeys = []
  //   if (selected) {
  //     _checkedKeys = [node.props.id]
  //   }
  //   dispatch(createAction('group/updateState')({
  //     groupIds: _checkedKeys
  //   }));
  // };
  const onExpand = expandedKeys => {
    setExpandedKeys(expandedKeys)
  }
  const onLoadData = async treeNode => {
    if (!treeNode.props.children) {
      const { data } = await getNodes({
          id: treeNode.props.id
      })
      treeNode.props.dataRef.children = data

      dispatch(createAction('group/updateState')({
        groups: [...groups]
      }))
    }
  }
  const onChange = activeKey => {
    setActiveKey(activeKey)
  }

  const [groupOptions, setGroupOptions] = useState([])

  const handleOptionSelect = (value, option) => {
    const ids = value.split('/')

    setExpandedKeys(ids)
  }
  const renderOption = item => {
    const { name, names } = getQueryKeywords(item.s, item.name)

    return (
      <AutoComplete.Option key={item.path} text={name}>
        <span dangerouslySetInnerHTML={{__html: names}}></span>
      </AutoComplete.Option>
    )
  }
  const searchResult = (s, data) => (data || []).map(item => ({
    ...item,
    s
  }))
  const handleTreeSearch = async value => {
    if (value) {
      const data = await search({
        s: value
      })
      setGroupOptions(searchResult(value, data))
    } else {
      setGroupOptions([])
    }
  }

  return (
    <Tabs activeKey={activeKey} layout="fixed" onChange={onChange}>
      <Tabs.TabPane tab="部门信息" key="1">
        <Form layout="vertical">
          <Form.Item label="部门名称">
            {getFieldDecorator('name', {
              rules: [
                {
                  required: true,
                  message: '请输入部门名称',
                },
                {
                  validator: async (rule, value, callback) => {
                    if (!value || value.trim() === '' || (data.name && data.name.trim() === value.trim())) return callback()
                    const invalid = await check({
                      [settings.valid]: value,
                    })
                    invalid ? callback('部门名称已存在') : callback();
                  },
                },
              ],
              initialValue: data.name,
            })(<Input placeholder="请输入" />)}
          </Form.Item>
          <Form.Item label="部门描述">
            {getFieldDecorator('desc', {
              // rules: [
              //   {
              //     message: '请输入至少五个字符的部门描述！',
              //     min: 5,
              //   },
              // ],
              initialValue: data.desc,
            })(<Input.TextArea rows={8} placeholder="请输入备注信息" />)}
          </Form.Item>
        </Form>
      </Tabs.TabPane>
      <Tabs.TabPane tab="所属部门" key="2">
        <div className="x-query fixed">
          <AutoComplete
            dataSource={groupOptions.map(renderOption)}
            onSelect={handleOptionSelect}
            onSearch={handleTreeSearch}
            placeholder="请输入部门名称"
            optionLabelProp="text"
          >
            <Input suffix={<Icon name="search" />} />
          </AutoComplete>
        </div>
        <Tree
          checkable
          // multiple
          showIcon
          loadData={onLoadData}
          expandedKeys={expandedKeys}
          onExpand={onExpand}
          checkedKeys={groupIds}
          // selectedKeys={selectedKeys}
          checkStrictly
          rowKey={record => record.id}
          onCheck={onCheck}
          // onSelect={onSelect}
        >
          {renderTreeNodes(groups)}
        </Tree>
      </Tabs.TabPane>
      <Tabs.TabPane tab="所属角色" key="3">
        <Transfer
          rowKey={record => record.id}
          showSearch
          dataSource={roles}
          listStyle={{
            width: 210,
            height: 340,
          }}
          targetKeys={roleIds}
          onChange={handleChange}
          render={item => item.name}
        />
      </Tabs.TabPane>
    </Tabs>
  );
})

const UnitPage = props => {
  const dispatch = useDispatch()
  const [loadedKeys, setLoadedKeys] = useState([])
  const [expandedKeys, setExpandedKeys] = useState([])
  const [selectedKeys, setSelectedKeys] = useState([])
  const { nodes= [] } = useSelector(_ => _.group)

  const {
    route,
    location,
    children
  } = props;

  useEffect(() => {
    dispatch(createAction('group/fetchNodes')());
  }, [dispatch]);
  const handleMenuEvent = (e, key) => {
    e.stopPropagation()

    const id = selectedKeys[0]

    dispatch(createAction('group/reset')());

    switch (key) {
      case 'add':
        Dialog.open({
          title: '新建部门',
          fixed: true,
          effect: true,
          url: api.group_add,
          data: {
            id
          },
          component: ModelForm,
          onOk: data => {
            handleTreeReload();
          }
        });
        break;
      case 'edit':
        Dialog.open({
          title: '修改部门',
          fixed: true,
          effect: true,
          url: api.group_update,
          data: {
            id,
          },
          // options: {
          //   type: 'put',
          // },
          onOk: data => {
            handleTreeReload();
          },
          component: props => <ModelForm {...props} id={id} />,
          connect: ({ loading }) => ({ loading: loading.effects['group/fetchNode'] }),
        });
        break;
      case 'remove':
        Dialog.confirm({
          title: '确认提示',
          content: '确定要删除已选择的部门？',
          onOk: async () => {
            await dispatch(createAction('group/deleteNode')({
              id
            }))
            setSelectedKeys([])
            setExpandedKeys(expandedKeys.filter(_ => _.id !== id))
            handleTreeReload();
          },
        });
        break;
      default:
    }
  };
  const onSelect = (selectedKeys, { selected }) => {
    setSelectedKeys(selectedKeys);
  };
  const onExpand = expandedKeys => {
    setExpandedKeys(expandedKeys)
  }
  const onLoad = loadedKeys => {
    setLoadedKeys(loadedKeys)
  }
  const handleTreeReload = () => {
    dispatch(createAction('group/resetNodes')());
    setLoadedKeys([])
    dispatch(createAction('group/fetchNodes')());
  };
  const onLoadData = async treeNode => {
    if (!treeNode.props.children) {
      const { data } = await getNodes({
          id: treeNode.props.id
      })
      treeNode.props.dataRef.children = data

      dispatch(createAction('group/updateState')({
        nodes: [...nodes]
      }))
    }
  }
  const renderTreeNodes = (data = []) =>
    data.map(item => {
      if (item.children) {
        return (
          <TreeNode title={item.name} key={item.id} dataRef={item} icon={<Icon name="folder-open" />}>
            {renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode {...item} title={item.name} key={item.id} dataRef={item} icon={<Icon name="folder-open" />} />;
    });
  const getContext = () => {
    return {
      groupId: selectedKeys.length ? selectedKeys[0] : null
    }
  }

  const [dataSource, setDataSource] = useState([])

  const handleOptionSelect = (value, option) => {
    const ids = value.split('/')
    const id = ids[ids.length - 1]

    setExpandedKeys(ids)
    setSelectedKeys([id])
  }
  const renderOption = item => {
    const { name, names } = getQueryKeywords(item.s, item.name)

    return (
      <AutoComplete.Option key={item.path} text={name}>
        <span dangerouslySetInnerHTML={{__html: names}}></span>
      </AutoComplete.Option>
    )
  }
  const searchResult = (s, data) => (data || []).map(item => ({
    ...item,
    s
  }))
  const handleTreeSearch = async value => {
    if (value) {
      const data = await search({
        s: value
      })
      setDataSource(searchResult(value, data))
    } else {
      setDataSource([])
    }
  }

  return (
    <Layout
      tools={
        <React.Fragment>
          <Button type="button" className="ico-btn" onClick={e => handleMenuEvent(e, 'add')}><Icon name="plus-square" /></Button>
          <Button type="button" className="ico-btn" onClick={e => handleMenuEvent(e, 'edit')} disabled={selectedKeys.length !== 1}><Icon name="edit" /></Button>
          <Button type="button" className="ico-btn" onClick={e => handleMenuEvent(e, 'remove')} disabled={selectedKeys.length !== 1}><Icon name="minus-square" /></Button>
        </React.Fragment>
      }
      query={
        <AutoComplete
          dataSource={dataSource.map(renderOption)}
          onSelect={handleOptionSelect}
          onSearch={handleTreeSearch}
          placeholder="请输入节点名称"
          optionLabelProp="text"
        >
          <Input suffix={<Icon name="search" />} />
        </AutoComplete>
      }
      side={{
        width: 280,
        component: <Tree
                      defaultExpandAll
                      showIcon
                      loadData={onLoadData}
                      rowKey={record => record.id}
                      loadedKeys={loadedKeys}
                      onLoad={onLoad}
                      expandedKeys={expandedKeys}
                      onExpand={onExpand}
                      selectedKeys={selectedKeys}
                      onSelect={onSelect}
                      >
                      {renderTreeNodes(nodes)}
                    </Tree>
        }
      }
    >
      {
        selectedKeys.length > 0 ?
          <TabManager
            route={route}
            location={location}
          >
            <GroupContext.Provider value={getContext()}>
              {children}
            </GroupContext.Provider>
          </TabManager>
          :
          <Layout>
            <Layout.Hello></Layout.Hello>
          </Layout>
      }
    </Layout>
  );
}

export default UnitPage;
